/*  yALB - Yet Another List Builder (roster Editor for Wargames/tabletop games).
    Copyright (C) 2008-2012  Daniel Ricardo Castro Alvarado

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/

#ifndef COLLECTION_H
#define COLLECTION_H

#include <QObject>
#include <QHash>

#include "errorhandler.h"

namespace CollectionPrivate {
class CollectionBase : public QObject
{
    Q_OBJECT
public:
    CollectionBase() { }
signals:
    void elementAdded(const QString& key);
    void elementUpdated(const QString& oldKey, const QString& newKey);
    void elementRemoved(const QString& key);

    void modified();
    void cleared();
};
}

template <class T>
class Collection : public CollectionPrivate::CollectionBase
{
public:
    Collection() : showMessages(true), errorHandler(NULL) { }

    // Copy operators

    Collection& operator=(const Collection& other) {
        this->internalCollection = QHash<QString, T>(other.internalCollection);
        return *this;
    }
    Collection(const Collection& other) { *this = other; }


    // Adds "element" with key "key" to the collection
    void addElement(const T& element, const QString &key);

    // Updates the element with key "currentKey" to "newElement" with "newKey"
    void updateElement(const QString& currentKey, const T& newElement,
                const QString& newKey);

    // Removes the specified key
    void removeElement(const QString& key);

    // Adds a clone of the specified key to the collection. Returns the added key (or empty if it wasn't added)
    QString cloneKey(const QString& key);

    // Deletes all keys
    void clearAll();

    // Sets a new ErrorHandler and returns the old one
    ErrorHandler* setErrorHandler(ErrorHandler* newHandler);

    // START Inline functions

    // Returns a copy of the element with the specified key (or a default constructed value)
    inline T get(const QString& key) const { return internalCollection.value(key); }

    // Returns a pointer to the element with the specified key or NULL if it does not exist
    inline T* getRealElement(const QString& key) {
        if(internalCollection.contains(key)) {
            return &internalCollection[key];
        } else {
            return NULL;
        }
    }

    // Returns true if the key exists in the collection
    inline bool contains(const QString& key) const { return internalCollection.contains(key); }

    // Returns a list of the keys in the collection
    inline QStringList keys() const { return internalCollection.keys(); }

    // Returns a list with the values in the collection
    inline QList<T> values() const { return internalCollection.values(); }

    // Determines if the collection should show messages in case of errors while adding, updating or removing keys
    inline void setShowMessages(bool value) { showMessages = value; }

    // Reduces the used memory after adding items.
    inline void squeeze() { internalCollection.squeeze(); }

    // END Inline functions

private:
    QHash<QString, T> internalCollection;
    bool showMessages;
    ErrorHandler *errorHandler;
};

#endif // COLLECTION_H
